package com.fjec.common.aspect;

import com.fjec.common.eventbus.event.VisitLogEvent;
import com.fjec.common.shiro.AccountInfo;
import com.fjec.common.util.JsonUtil;
import com.google.common.eventbus.EventBus;
import lombok.extern.slf4j.Slf4j;
import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;
import org.aspectj.lang.reflect.MethodSignature;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;

import java.lang.reflect.Method;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;

@Slf4j
@Aspect
@Component
@Order(AspectOrder.VisitAspect)
public class VisitAspect extends BaseAspect {

    @Autowired
    private EventBus eventBus;

    @Around("execution(public * com.fjec.*.controller..*.*(..))")
    public Object around(ProceedingJoinPoint point) throws Throwable {
        long startTime = System.currentTimeMillis();
        try {
            Object result =  point.proceed();
            long useTime = System.currentTimeMillis() - startTime;
            broadcastLog(point,null,result,useTime);
            return result;
        } catch (Throwable e) {
            long useTime = System.currentTimeMillis() - startTime;
            broadcastLog(point, e,null,useTime);
            /*if (!(e instanceof OperationException)) {
                broadcastErrotLog(point, e,null);
            }*/
            throw e;
        }
    }

    private void broadcastLog(ProceedingJoinPoint point, Throwable throwable, Object result , long useTime ) {
        MethodSignature ms = (MethodSignature) point.getSignature();
        Method method = ms.getMethod();

        String methodName = method.getName();
        String className = point.getTarget().getClass().getName();

        Map<String, Object> argsMap = this.getParameters(ms.getParameterNames(), point.getArgs());
        //构造日志事件
        VisitLogEvent event = new VisitLogEvent();
        event.setThreadName(Thread.currentThread().getName());
        event.setClassName(className);
        event.setMethodName(methodName);
        event.setHappenTime(new Date());
        event.setArgsMap(argsMap);
        event.setArgsJson(JsonUtil.toJson(argsMap));
        event.setThrowable(throwable);
        event.setTraceId("VISIT_LOG");
        event.setResult(result);
        event.setUseTime(useTime);
        if (AccountInfo.isAuthenticated()) {
            Map<String, Object> userMap = new HashMap<>();
            userMap.put("userId", AccountInfo.getUserId());
            userMap.put("userName", AccountInfo.getUserName());
            userMap.put("nickName", AccountInfo.getWxNickName());
            userMap.put("shopName", AccountInfo.getShopName());
            event.setUserMap(userMap);
        }
        eventBus.post(event);
    }
}
